package cn.com.okgotest.utils;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Logger;

import cn.com.okgo.OkGo;

/**
 * Created by luwenlong on 2017/9/28.
 */

public class BitmapUtils {
    private final static String TAG = "BitmapUtils";

    /**
     * 将Drawable图片 转 Base64字符串
     */
    public static String drawableToBase64(int drawableId) {
        return bitmapToBase64( BitmapFactory.decodeResource( OkGo.getContext().getResources(), drawableId));
    }

    /**
     * 将Base64字符串 转 Bitmap
     */
    public static Bitmap base64ToBitmap(String base64Str) {
        try {
            // Base64编码默认采用 Base64.DEFAULT, 当字符串过长(一般超过76)时会自动添加换行符(\n等);
            byte[] bytes;
            if (base64Str.contains("\n"))
                bytes = Base64.decode(base64Str, Base64.DEFAULT);
            else
                bytes = Base64.decode(base64Str, Base64.NO_WRAP);       // 指定采用 NO_WRAP 省略所有行结束符
            return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        }catch (Exception e){
            Log.e(TAG, e.getMessage());
            return null;
        }
    }

    /**
     * 将Base64字符串 转 Bitmap
     * @param base64Str         图片Base64字符串
     * @param bitmapSize        图片压缩大小
     * @return
     */
    public static Bitmap base64ToBitmap(String base64Str, int bitmapSize) {
        // 1. base64转Bitmap对象; 2. 将Bitmap中透明色替换为白色(需优先于压缩); 3. 压缩Bitmap对象, 避免微信分享等失败;
        return compressBitmapSize(BitmapUtils.changeColor(base64ToBitmap(base64Str)), bitmapSize);
    }

    /**
     * 将Bitmap 转 Base64字符串
     * @param bitmap            图标Bitmap对象
     * @return
     */
    public static String bitmapToBase64(Bitmap bitmap) {
        String result = "";
        ByteArrayOutputStream bos = null;
        try {
            if (null != bitmap) {
                bos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.PNG, 90, bos);//将bitmap放入字节数组流中

                bos.flush();//将bos流缓存在内存中的数据全部输出，清空缓存
                bos.close();

                byte[] bitmapByte = bos.toByteArray();
                result = Base64.encodeToString(bitmapByte, Base64.NO_WRAP);
            }
        } catch (Exception e) {
        } finally {
            closeFileStream(bos);
        }
        return result;
    }

    /**
     * 压缩Bitmap至指定大小(例: 微信分享用32kb)
     * @param bitmap
     * @param bitmapSize
     * @return
     */
    public static Bitmap compressBitmapSize(Bitmap bitmap, int bitmapSize) {
        Bitmap compressBitmap = null;
        ByteArrayOutputStream bos = null;
        ByteArrayInputStream bis = null;
        if (bitmap != null) {
            try {
                bos = new ByteArrayOutputStream();
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
                int options = 100;
                while (bos.toByteArray().length / 1024 > bitmapSize) {
                    bos.reset();
                    bitmap.compress(Bitmap.CompressFormat.JPEG, options, bos);
                    options -= 10;//每次都减少10
                }
                bitmap.recycle();
                bis = new ByteArrayInputStream(bos.toByteArray());
                compressBitmap = BitmapFactory.decodeStream(bis, null, null);
            } catch (Exception e) {
            } finally {
                closeFileStream(bos);
                closeFileStream(bis);
            }
        }
        return compressBitmap;
    }

    /**
     * 将BitmapFile转换成base64字符串
     *
     * @param file
     * @param bitmapSize
     * @return
     */
    public static String decodeBitmapFiletoString(File file, int bitmapSize) {
        // 将Bitmap转换成字符串
        String baseStr = null;
        ByteArrayOutputStream bStream = new ByteArrayOutputStream();
        Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
        int option = 100;
        try {
            bitmap.compress(Bitmap.CompressFormat.JPEG, option, bStream);
            while (bStream.size() / 1024 >= bitmapSize) {
                option -= 10;
                bitmap.compress(Bitmap.CompressFormat.JPEG, option, bStream);
            }
            byte[] bytes = bStream.toByteArray();
            baseStr = Base64.encodeToString(bytes, Base64.DEFAULT);
            bitmap.recycle();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            closeFileStream(bStream);
        }
        return baseStr;
    }

    /** 关闭流 */
    public static void closeFileStream(Closeable fileStream) {
        if (null != fileStream) {
            try {
                fileStream.close();
            } catch (IOException e) {
            }
        }
    }


    /**
     * bitmap中的透明色用白色替换
     *
     * @param bitmap
     * @return
     */
    public static Bitmap changeColor(Bitmap bitmap) {
        if (bitmap == null) {
            return null;
        }
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        int[] colorArray = new int[w * h];
        int n = 0;
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                int color = getMixtureWhite(bitmap.getPixel(j, i));
                colorArray[n++] = color;
            }
        }
        return Bitmap.createBitmap(colorArray, w, h, Bitmap.Config.ARGB_8888);
    }

    /**
     * 获取和白色混合颜色
     *
     * @return
     */
    private static int getMixtureWhite(int color) {
        int alpha = Color.alpha(color);
        int red = Color.red(color);
        int green = Color.green(color);
        int blue = Color.blue(color);
        return Color.rgb(getSingleMixtureWhite(red, alpha), getSingleMixtureWhite

                        (green, alpha),
                getSingleMixtureWhite(blue, alpha));
    }

    /**
     * 获取单色的混合值
     *
     * @param color
     * @param alpha
     * @return
     */
    private static int getSingleMixtureWhite(int color, int alpha) {
        int newColor = color * alpha / 255 + 255 - alpha;
        return newColor > 255 ? 255 : newColor;
    }

    public static void clearImgMemory(View V) {
        if (V instanceof ImageView) {
            try{
                Drawable d = ((ImageView) V).getDrawable();
                if (d != null && d instanceof BitmapDrawable) {
                    Bitmap bmp = ((BitmapDrawable) d).getBitmap();
                    if(!bmp.isRecycled()){
                        bmp.recycle();
                        bmp = null;
                    }
                }
                ((ImageView) V).setImageBitmap(null);
                if (d != null) {
                    d.setCallback(null);
                }
            }catch (Exception e){
            }
        }
    }

    public static void releaseGroup(View view){
        if (view instanceof ViewGroup) {
            int count = ((ViewGroup)view).getChildCount();
            for (int i=0;i<count;i++) {
                View childView = ((ViewGroup)view).getChildAt(i);
                if (childView instanceof ViewGroup) {
                    releaseGroup(childView);
                }else {
                    BitmapUtils.clearImgMemory(childView);
                }
            }
        }else {
            BitmapUtils.clearImgMemory(view);
        }
    }

    /**
     * 简单压缩图片返回输出字节流(对于图片大小比较小的2M以内)
     * @param filePath
     * @param maxSize
     * @return
     */
    public static ByteArrayOutputStream compressAndGenImage(String filePath, int maxSize){
        Bitmap bitmap = getBitmap(filePath);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // scale
        int options = 100;
        // Store the bitmap into output stream(no compress)
        bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
        Log.e("-------size",baos.toByteArray().length + "");
        // Compress by loop 压缩图片
        while ( (baos.toByteArray().length / 1024 > maxSize)&& options > 10) {
            // Clean up os
            baos.reset();
            // interval 10
            options -= 10;
            bitmap.compress(Bitmap.CompressFormat.JPEG, options, baos);
        }
        return baos;
    }

    /**
     * Get bitmap from specified image path
     *
     * @param imgPath
     * @return
     */
    public static Bitmap getBitmap(String imgPath) {
        // Get bitmap through image path
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = false;
        newOpts.inPurgeable = true;
        newOpts.inInputShareable = true;
        // Do not compress
        newOpts.inSampleSize = 1;
        newOpts.inPreferredConfig = Bitmap.Config.RGB_565;
        return BitmapFactory.decodeFile(imgPath, newOpts);
    }

    /**
     * Store bitmap into specified image path
     *
     * @param bitmap
     * @param outPath
     * @throws FileNotFoundException
     */
    public static void storeImage(Bitmap bitmap, String outPath) throws FileNotFoundException {
        FileOutputStream os = new FileOutputStream(outPath);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
    }

    /**
     * 对原 bitmap 进行指定大小比例的缩放
     * @param bit
     * @param scale
     * @return
     */
    public static Bitmap getScaledBitmap(Bitmap bit, float scale){
        Matrix matrix = new Matrix();
        matrix.setScale(scale, scale);
        Bitmap bm = Bitmap.createBitmap(bit, 0, 0, bit.getWidth(),
                bit.getHeight(), matrix, true);
        bit.recycle();
        Log.d("getBitMapSize4", "压缩后图片的大小" + (bm.getByteCount() / 1024 / 1024)
                + "M宽度为" + bm.getWidth() + "高度为" + bm.getHeight());
        return bm;
    }

    /**
     * 精确压缩图片(包括文件2M以上的压缩)
     * @param imgPath
     * @param maxSize
     * @return
     */
    public static ByteArrayOutputStream getScaleBitMapBoas(String imgPath,int maxSize){
        long startTime = System.currentTimeMillis();
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        // 开始读入图片，此时把options.inJustDecodeBounds 设回true，即只读边不读内容
        newOpts.inJustDecodeBounds = true;
        newOpts.inPreferredConfig = Bitmap.Config.RGB_565;
        Bitmap bitmap1;
        ByteArrayOutputStream boas = new ByteArrayOutputStream();
        int len = (int) (new File(imgPath).length() / 1024.0f);
        int be = 1;
        if(len > maxSize){
            be = (int) Math.ceil(Math.sqrt(len / maxSize));
        }
        newOpts.inSampleSize = be;
        newOpts.inJustDecodeBounds = false;
        bitmap1 = BitmapFactory.decodeFile(imgPath, newOpts);//快速粗略的压缩大小
        bitmap1.compress(Bitmap.CompressFormat.JPEG, 100, boas);
        len = (int) (boas.toByteArray().length / 1024.0f);

        float scale = (float) Math.sqrt(0.8);//每次压缩的比例为0.8
        maxSize = (int) (maxSize * 1.2f);
        while(len > maxSize){//继续压缩知道达到指定的大小
            boas.reset();
            bitmap1 = getScaledBitmap(bitmap1,scale);
            bitmap1.compress(Bitmap.CompressFormat.JPEG, 100, boas);
            len = boas.toByteArray().length / 1024;
        }
        bitmap1.recycle();
        long endTime;
        endTime = System.currentTimeMillis();
        return boas;
    }

}
